﻿using NationalInstruments.TestStand.Interop.API;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection.Emit;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace CLVisionEICS
{
    internal class ProcessEICSData
    {
        //private JToken jToken;

        //public JToken CdatToEICSJson(string cdatPath, out int ErrorCode, out string ErrorText)
        //{
        //    ErrorCode = 0;
        //    ErrorText = "ProcessData.CdatToMesJson: Start!";
        //    JToken backToken = null;
        //    try
        //    {
        //        using (FileStream stream = new FileStream(cdatPath, FileMode.Open, FileAccess.Read, FileShare.Read))
        //        {
        //            using (StreamReader streamReader = new StreamReader(stream, Encoding.UTF8))
        //            {
        //                string json = streamReader.ReadToEnd();
        //                jToken = JToken.Parse(json);
        //            }
        //        }

        //        if (jToken == null)
        //        {
        //            ErrorCode = -1;
        //            ErrorText = "ProcessData.CdatToMesJson: 读取cdat数据异常！ ";
        //            return null;
        //        }
        //        TreeItemStruct treeItem = new TreeItemStruct();
        //        RemoveComment(jToken, ref treeItem, out ErrorCode, out ErrorText);

        //        var jObj = new JObject();
        //        TreeItemToJobject(treeItem, jObj, out ErrorCode, out ErrorText);

        //        ////报文头Json
        //        //string jsonString = EntityToJSON(new Fixdata()
        //        //{
        //        //    Identify = string.Empty,
        //        //    Line = string.Empty,
        //        //    time = string.Empty,
        //        //    station = string.Empty
        //        //});
        //        //JObject FixdataJson = JObject.Parse(jsonString);
        //        //JProperty fixdataProperty = new JProperty("Fixdata", FixdataJson); 

        //        //去除Root
        //        var token = jObj["Root"];

        //        //生成内容Json
        //        JToken retJson = new JObject();
        //        JobjectToEICSJsonStruct(token, ref retJson, out ErrorCode, out ErrorText);

        //        //创建Content节点
        //        JProperty contentProperty = new JProperty("Content", retJson);

        //        //拼MES数据
        //        JObject tempObj = new JObject();
        //        //tempObj.Add(fixdataProperty);

        //        //报文头Json

        //        JProperty jProperty = new JProperty("GroupId","");
        //        string jsonString = EntityToJSON(new Fixdata());
        //        //{
        //        //    GroupId = string.Empty,
        //        //    GroupCompleted = 0,
        //        //    GroupIndex = 0,
        //        //    EventId = string.Empty,
        //        //    EventName = string.Empty,
        //        //    ApplicationX = string.Empty,
        //        //    Line = string.Empty,
        //        //    LineId = 0,
        //        //    Station = string.Empty,
        //        //    StationId = string.Empty,
        //        //    Process = string.Empty,
        //        //    ProcessId = string.Empty,
        //        //    PanelId = string.Empty,
        //        //    Identifier = string.Empty,
        //        //    OldIdentifier = string.Empty,
        //        //    OperatorName = string.Empty,
        //        //    Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
        //        //});

        //        JObject jb= JObject.Parse(jsonString);
        //        foreach (var item in jb.Children<JProperty>())
        //        {
        //            tempObj.Add(item);
        //        }

        //        foreach (var item in token.Children<JProperty>())
        //        {
        //            tempObj.Add(item);
        //        }
        //        tempObj.Add(contentProperty);
        //        backToken = tempObj;

        //        ErrorText = "ProcessData.CdatToMesJson: End！";
        //        return backToken;
        //    }
        //    catch (Exception ex)
        //    {
        //        ErrorCode = -1;
        //        ErrorText = "ProcessData.CdatToMesJson: 读取cdat数据异常！" + ex.Message;
        //        return null;
        //    }
        //}

        public JToken CdatToEICSJson(string cdatPath, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: Start!";
            try
            {
                JToken jToken;
                using (FileStream stream = new FileStream(cdatPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (StreamReader streamReader = new StreamReader(stream, Encoding.UTF8))
                    {
                        string json = streamReader.ReadToEnd();
                        jToken = JToken.Parse(json);
                    }
                }
                if (jToken == null)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: 读取cdat数据异常！ ";
                    return null;
                }
                TreeItemStruct treeItem = new TreeItemStruct();
                RemoveComment(jToken, ref treeItem, out ErrorCode, out ErrorText);
                if (ErrorCode == -1)
                {
                    ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: 移除注释失败！{ErrorText} ";
                    return null;
                }


                var jObj = new JObject();
                TreeItemToJobject(treeItem, jObj, out ErrorCode, out ErrorText);
                if (ErrorCode == -1)
                {
                    ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: 数据转换为Jobject失败！{ErrorText} ";
                    return null;
                }

                //提取Root节点下数据
                var token = jObj["Root"];

                //生成内容Json
                JToken eicsJson = new JObject();
                JobjectToEICSJsonStruct(token, ref eicsJson, out ErrorCode, out ErrorText);
                if (ErrorCode == -1)
                {
                    ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: Jobject转换为EICS数据结构失败！{ErrorText} ";
                    return null;
                }

                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: End！";
                return eicsJson;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(CdatToEICSJson)}: 读取cdat数据异常！" + ex.Message;
                return null;
            }
        }

        public void RemoveComment(JToken jToken, ref TreeItemStruct treeItem, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(ProcessEICSData)}:{nameof(RemoveComment)}: Start!";
            try
            {
                switch (jToken.Type)
                {
                    case JTokenType.None:
                        break;
                    case JTokenType.Object:
                        DataGridItemStruct temp = null;
                        foreach (JProperty property in jToken.Children<JProperty>())
                        {
                            //判断当前键值对是否是注释
                            if (property.Name.Contains("#"))
                            {
                                continue;
                            }

                            //判断当前键值对的值类型  不是JObject也不是JArray
                            if (property.Value.Type != JTokenType.Array && property.Value.Type != JTokenType.Object)
                            {
                                DataGridItemStruct dataGridItemStruct = new DataGridItemStruct();
                                dataGridItemStruct.Key = property.Name;
                                dataGridItemStruct.Value = TransData(property.Value, property.Value.Type, out ErrorCode, out ErrorText);
                                dataGridItemStruct.ValueList = dataGridItemStruct.DataGridComments.ValueList;
                                dataGridItemStruct.Type = (EnumDataType)Enum.Parse(typeof(EnumDataType), property.Value.Type.ToString().ToUpper());

                                //类型下拉列表绑定到枚举类，当前TypeList存放默认选中的值
                                dataGridItemStruct.TypeList.Add(dataGridItemStruct.Type);
                                treeItem.DataGridStructOfTreeItem.DataGridItemStructs.Add(dataGridItemStruct);
                                temp = dataGridItemStruct;
                                continue;
                            }
                            //键值对的值为 JObject
                            TreeItemStruct treeChildItem = new TreeItemStruct();
                            treeChildItem.Name = property.Name;
                            treeChildItem.Parent = treeItem;
                            treeItem.Children.Add(treeChildItem);

                            RemoveComment(property.Value, ref treeChildItem, out ErrorCode, out ErrorText);
                        }
                        break;
                    case JTokenType.Array:
                        //treeItem.ImagePath = "/Resources/Image/array.png";
                        treeItem.IsArray = true;
                        int Length = jToken.Count();
                        for (int i = 0; i < jToken.Count(); i++)
                        {
                            //判断数组中一个元素类型   判断数组中的元素 是类还是值

                            if (jToken[i].Type == JTokenType.Object)     //元素 是类
                            {
                                //遍历数组下的类元素
                                foreach (JProperty property in jToken[i].Children<JProperty>())
                                {
                                    TreeItemStruct treeChildItem = new TreeItemStruct();
                                    treeChildItem.Name = property.Name;
                                    treeChildItem.Parent = treeItem;
                                    treeChildItem.IsArray = true;
                                    treeChildItem.ArrayIndex = i;
                                    treeItem.Children.Add(treeChildItem);
                                    RemoveComment(property.Value, ref treeChildItem, out ErrorCode, out ErrorText);
                                }
                            }
                            else  //数组中元素 单个值
                            {
                                int index = 0;
                                foreach (var item in jToken)
                                {
                                    DataGridItemStruct dataGridItemStruct = new DataGridItemStruct();
                                    dataGridItemStruct.Key = $"[{index}]";
                                    dataGridItemStruct.Value = TransData(item, item.Type, out ErrorCode, out ErrorText);
                                    dataGridItemStruct.ValueList = dataGridItemStruct.DataGridComments.ValueList;
                                    dataGridItemStruct.Type = (EnumDataType)Enum.Parse(typeof(EnumDataType), item.Type.ToString().ToUpper());
                                    dataGridItemStruct.TypeList.Add(dataGridItemStruct.Type);
                                    treeItem.DataGridStructOfTreeItem.DataGridItemStructs.Add(dataGridItemStruct);
                                    index++;
                                    JProperty property = (JProperty)jToken.Parent.Next;
                                }
                                break;
                            }
                        }
                        break;
                }
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(RemoveComment)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(RemoveComment)}: Fail!" + ex.Message;
            }
        }

        private object TransData(JToken value, JTokenType dataType, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(ProcessEICSData)}:{nameof(TransData)}: Start!";
            try
            {
                switch (dataType)
                {
                    case JTokenType.Integer: return (int)value;
                    case JTokenType.Float: return (double)value;
                    case JTokenType.String: return value.ToString();
                    case JTokenType.Boolean: return (bool)value;
                    default: return (int)value;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(TransData)}: Fail!" + ex.Message;
                return null;
            }
        }

        public void TreeItemToJobject(TreeItemStruct treeItem, JToken token, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(ProcessEICSData)}:{nameof(TreeItemToJobject)}: Start!";
            try
            {
                foreach (var itemChild in treeItem.Children)
                {
                    if (!itemChild.IsArray)
                    {
                        JObject jObjectTreeItem = new JObject();
                        JProperty jPropertyTreeItem = new JProperty(itemChild.Name, jObjectTreeItem);
                        ((JObject)token).Add(jPropertyTreeItem);
                        //itemChild不是数组，DataGridItemStructs中数据为键值对
                        foreach (DataGridItemStruct dataGridItem in itemChild.DataGridStructOfTreeItem.DataGridItemStructs)
                        {
                            //创建键值对
                            JProperty jPropertyDataGridItem = new JProperty(dataGridItem.Key, dataGridItem.Value);
                            jObjectTreeItem.Add(jPropertyDataGridItem);
                        }
                        TreeItemToJobject(itemChild, jObjectTreeItem, out ErrorCode, out ErrorText);
                    }
                    else
                    {
                        JArray jArrayTreeItem = new JArray();
                        JProperty jPropertyDataGridItem = new JProperty(itemChild.Name, jArrayTreeItem);
                        if (token.Type == JTokenType.Array)
                        {
                            ((JArray)token).Add(new JObject(jPropertyDataGridItem));
                        }
                        else if (token.Type == JTokenType.Object)
                        {
                            ((JObject)token).Add(jPropertyDataGridItem);
                        }
                        foreach (DataGridItemStruct dataGridItem in itemChild.DataGridStructOfTreeItem.DataGridItemStructs)
                        {
                            jArrayTreeItem.Add(dataGridItem.Value);
                        }
                        TreeItemToJobject(itemChild, jArrayTreeItem, out ErrorCode, out ErrorText);
                    }
                }
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(TreeItemToJobject)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(TreeItemToJobject)}: Fail!" + ex.Message;
            }
        }

        public void JobjectToEICSJsonStruct(JToken jToken, ref JToken rootJson, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(ProcessEICSData)}:{nameof(JobjectToEICSJsonStruct)}: Start!";
            try
            {
                foreach (JProperty item in jToken.Children<JProperty>())
                {
                    if (item.Value.Type != JTokenType.Object)
                    {
                        continue;
                    }
                    var name = item.Value["name"].ToString();
                    //int value = (int)item.Value["dataType"];
                    string dataType = item.Value["dataType"].ToString();
                    //var HierNo = item.Value["HierNo"];
                    //var LastHierNo = item.Value["LastHierNo"];
                    //var ArrayEnable = item.Value["ArrayEnable"];
                    JToken contentValue = null;
                    JToken jProperty = null;

                    switch ((EnumDataType)Enum.Parse(typeof(EnumDataType), dataType.ToUpper()))
                    {
                        case EnumDataType.BOOLEAN:
                            contentValue = false;
                            jProperty = new JProperty(name, contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            break;
                        case EnumDataType.INTEGER:
                            contentValue = 0;
                            jProperty = new JProperty(name, contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            break;
                        case EnumDataType.INT:
                         contentValue = 0;
                            jProperty = new JProperty(name, contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            break;
                        case EnumDataType.FLOAT:
                            contentValue = 0.0;
                            jProperty = new JProperty(name, contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            break;
                        case EnumDataType.DOUBLE:
                            contentValue = 0.0;
                            jProperty = new JProperty(name, contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            break;
                        case EnumDataType.STRING:
                            contentValue = string.Empty;
                            jProperty = new JProperty(name, contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            break;
                        case EnumDataType.CLASS:
                            JArray jArray = new JArray();
                            jProperty = new JProperty(name, jArray);
                            contentValue = new JObject();
                            jArray.Add(contentValue);
                            ((JObject)rootJson).Add(jProperty);
                            JobjectToEICSJsonStruct(item.Value, ref contentValue, out ErrorCode, out ErrorText);
                            break;
                    }
                }
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(JobjectToEICSJsonStruct)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(JobjectToEICSJsonStruct)}: Fail!" + ex.Message;
            }

        }

        public void SaveJsonToFile(string jsonPath, JToken token, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(ProcessEICSData)}:{nameof(SaveJsonToFile)}: Start!";
            try
            {
                using (FileStream fs = new FileStream(jsonPath, FileMode.Create, FileAccess.Write, FileShare.Write))
                {
                    using (StreamWriter streamWriter = new StreamWriter(fs))
                    {
                        streamWriter.Write(token.ToString());
                    }
                }
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(SaveJsonToFile)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(ProcessEICSData)}:{nameof(SaveJsonToFile)}: Fail!" + ex.Message;
            }
        }


        // 实体对象转换成JSON字符串
        public string EntityToJSON<T>(T x)
        {
            string result = string.Empty;

            try
            {
                result = JsonConvert.SerializeObject(x);
            }
            catch (Exception)
            {
                result = string.Empty;
            }
            return result;

        }
    }
}
